from decimal import Decimal

from rest_framework import viewsets, filters, status
from rest_framework.decorators import action
from rest_framework.response import Response
from django.db.models import *
from .models import Employee
from staff.staffserializers import EmployeeSerializer
from django_filters.rest_framework import DjangoFilterBackend
import datetime
from django.db.models.functions import Coalesce, Cast  # 处理字段为NULL的情况
import calendar


class EmployeeViewSet(viewsets.ModelViewSet):
    queryset = Employee.objects.all()
    serializer_class = EmployeeSerializer
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    # 筛选 部门、状态、学历、性别信息 可扩展
    filterset_fields = ['department', 'status', 'degree', 'gender']
    # 搜索 按名字、工号、手机号 身份证号、职位 可扩展
    search_fields = ['name', 'work_id', 'phone', 'id_number', 'position']

    # detail=False 表示当前属于一个集合模块 设置为Ture则表示这是一个单模块  因为是搜索功能表示只接受get请求
    @action(detail=False, methods=['get'])
    def search(self, request):
        params = request.query_params
        queryset = self.filter_queryset(self.get_queryset())
        # 处理入职时间范围查询
        entry_start = params.get('entry_start')
        entry_end = params.get('entry_end')
        if entry_start and entry_end:
            try:
                # 入职时间  将数据库入职时间软换成可处理格式 方便查询
                start_date = datetime.datetime.strptime(entry_start, '%Y-%m-%d')
                # 到期时间  将数据库离职时间软换成可处理格式 方便查询
                end_date = datetime.datetime.strptime(entry_end, '%Y-%m-%d')
                # 返回一个查询集  entry_time__range是一个字段查询语法
                queryset = queryset.filter(entry_time__range=(start_date, end_date))
            except ValueError:
                pass

        # 将 queryset查询集序列化  many=True 表示要序列化多个对象
        serializer = self.get_serializer(queryset, many=True)
        return Response({
            'employees': serializer.data,
            'count': queryset.count()
        })

    @action(detail=False, methods=['post'])
    def batch_delete(self, request):
        ids = request.data.get('ids', [])
        if not ids:
            return Response({'error': '未选择任何员工'}, status=status.HTTP_400_BAD_REQUEST)
        if not isinstance(ids, list) or not all(isinstance(id, int) for id in ids):
            return Response({'error': '无效的ID格式'}, status=status.HTTP_400_BAD_REQUEST)
        deletable = Employee.objects.filter(id__in=ids, status='在职')
        deleted_count, _ = deletable.delete()
        response = {
            'message': f'成功删除{deleted_count}名员工',
            'deleted_count': deleted_count
        }

        return Response(response)

    # 学历占比分布
    @action(detail=False, methods=['get'])
    def degree_stats(self, request):
        degree_annotate = Employee.objects.values('degree').annotate(
            count=Count('id')
        ).order_by('-count')
        values = []
        for item in degree_annotate:
            degree_type = item['degree']
            count = item['count']
            values.append({
                'type': degree_type,
                'value': count
            })

        result = {
            "data": [
                {
                    "id": "id0",
                    "values": values
                }
            ]
        }

        return Response(result)

    # 人力成本计算
    @action(detail=False, methods=['get'])
    def cost_value(self, request):
        active_employees = Employee.objects.filter(status='在职')
        total_monthly_cost = active_employees.aggregate(
            total=Sum('salary', default=Decimal('0.0'))  # 直接求和，默认0.0
        )['total']

        today = datetime.date.today()
        _, days_in_month = calendar.monthrange(today.year, today.month)
        daily_cost = total_monthly_cost / days_in_month if days_in_month != 0 else Decimal('0.0')

        department_ratio_name = active_employees.values("department").annotate(
            total_cost=Sum('salary', default=Decimal('0.0'))

        ).order_by('-total_cost')  # -total_cost “-“表示降序

        department_ratio = [
            {
                "department_name":d['department'],
                "ratio":round(float(d['total_cost'] / total_monthly_cost * 100 if total_monthly_cost != 0 else 0),2)
            }
            for d in department_ratio_name[:3]
        ]

        return Response({
            "daily_cost": round(float(daily_cost), 2),
            "total_monthly_cost": float(total_monthly_cost),
            "department_cost": department_ratio
        })
